<?php

class DbGateway
{
    protected static $_instance;
    protected $_dbConnection;
    protected $_params = array();

    protected function __construct()
    {
        $db = Config::get('db');
        try
        {
            $this->_dbConnection = new PDO
                (
                    $db['dsn'],
                    $db['user'],
                    $db['password'],
                    array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'')
                );
        }
        catch (PDOException $e)
        {
            $exception = new FatalException('Database could not connect!', 0, $e);
            $exception->setDebugData('dsn', $db['dsn']);
            $exception->setDebugData('user', $db['user']);
            $exception->setDebugData('password', $db['password']);
            throw $exception;
        }
    }

    public static function getConnection()
    {
        if (empty(self::$_instance))
        {
            self::$_instance = new DbGateway();
        }

        return self::$_instance;
    }

    public function bindParam($name, $value)
    {
        $this->_params[$name] = $value;
    }

    public function fetchSingle($sql)
    {
        $sth = $this->_dbConnection->prepare($sql);

        foreach ($this->_params as $name => $value)
        {
            $sth->bindValue($name, $value);
        }

        if (!$sth->execute())
        {
            $exception = new FatalException('Database query failed!');

            $db_error_info = $sth->errorInfo();
            $exception->setDebugData('db_error_info', $db_error_info);

            $exception->setDebugData('sql', $sql);
            $exception->setDebugData('params', $this->_params);
            throw $exception;
        }

        $this->_params = array();

        return $sth->fetch(PDO::FETCH_ASSOC);
    }

    public function fetchAll($sql)
    {
        $sth = $this->_dbConnection->prepare($sql);

        foreach ($this->_params as $name => $value)
        {
            $sth->bindValue($name, $value);
        }

        if (!$sth->execute())
        {
            $exception = new FatalException('Database query failed!');

            $db_error_info = $sth->errorInfo();
            $exception->setDebugData('db_error_info', $db_error_info);

            $exception->setDebugData('sql', $sql);
            $exception->setDebugData('params', $this->_params);
            throw $exception;
        }

        $this->_params = array();

        return $sth->fetchAll(PDO::FETCH_ASSOC);
    }

    public function affect($sql)
    {
        $sth = $this->_dbConnection->prepare($sql);

        foreach ($this->_params as $name => $value)
        {
            $sth->bindValue($name, $value);
        }

        if (!$sth->execute())
        {
            $exception = new FatalException('Database query failed!');

            $db_error_info = $sth->errorInfo();
            $exception->setDebugData('db_error_info', $db_error_info);

            $exception->setDebugData('sql', $sql);
            $exception->setDebugData('params', $this->_params);
            throw $exception;
        }

        $this->_params = array();

        return $sth->rowCount();
    }
}

?>